﻿using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using UnityEngine;
using UnityEngine.UI;

public class MainView : MonoBehaviour
{
    public RangeDeviceView RangeDevViewTemplate;
    public ToggleDeviceView ToggleDeviceViewTemplate;
    public RectTransform ListRoot;

    public GameObject DevicesPanel;
    public GameObject LogPanel;

    public Button BtnDevices;
    public Button BtnLog;
    public Button BtnOpenCfg;

    public Button BtnClearAll;
    public Button BtnClearAllToMin;
    public Button BtnClearAllToMax;

    public InputField InputUDPSendIP;
    public InputField InputUDPSendPort;
    public InputField InputUDPSendData;
    public Button BtnUDPSend;

    /// <summary>
    /// 回应设备查询时，json字符串是格式化还是扁平
    /// </summary>
    public Toggle ToggleUDPDevRspFmt;


    public LogLineView LogLineViewTemplate;
    public RectTransform LogListRoot;
    public LogLineContentView LogLine;

    public Toggle ToggleLogUDPDevReq;
    public Toggle ToggleLogUDPDevRsp;

    public Toggle ToggleLogInfo;
    public Toggle ToggleLogWarning;
    public Toggle ToggleLogError;
    public Button BtnClearLog;

    UDPModule UDP;
    Logger MyLogger;

    List<LogLineView> _lineViewPool = new List<LogLineView>(50);

    // Start is called before the first frame update
    IEnumerator Start()
    {
        UDP = FindObjectOfType<UDPModule>();
        MyLogger = FindObjectOfType<Logger>();
        UnityEngine.Debug.Assert(UDP != null);
        UnityEngine.Debug.Assert(MyLogger != null);

        LogLine.SetText("");
        MyLogger.onLogChanged += (logger) => {
            UpdateLogLines();
        };

        BtnDevices.onClick.AddListener(() => {
            DevicesPanel.SetActive(true);
            LogPanel.SetActive(false);
        });

        BtnLog.onClick.AddListener(() => {
            DevicesPanel.SetActive(false);
            LogPanel.SetActive(true);
        });

        BtnOpenCfg.onClick.AddListener(() =>
        {
            string path = Application.streamingAssetsPath.Replace("/", "\\");
            Process.Start("explorer.exe", $"\"{path}\"");
        });

        BtnDevices.onClick.Invoke();

        yield return new WaitForEndOfFrame();
        yield return new WaitForEndOfFrame();
        yield return new WaitForEndOfFrame();

        var devList = DeviceManager.Instance.GetAllDevices();
        foreach (var dev in devList)
        {
            if (dev is RangeDevice)
            {
                var itemView = Instantiate<GameObject>(RangeDevViewTemplate.gameObject);
                itemView.GetComponent<RangeDeviceView>().Device = dev as RangeDevice;
                itemView.transform.SetParent(ListRoot, false);
            }
            else if (dev is ToggleDevice)
            {
                var itemView = Instantiate<GameObject>(ToggleDeviceViewTemplate.gameObject);
                itemView.GetComponent<ToggleDeviceView>().Device = dev as ToggleDevice;
                itemView.transform.SetParent(ListRoot, false);
            }
        }

        BtnClearAll.onClick.AddListener(() => {
            var list = DeviceManager.Instance.GetAllDevices();
            foreach (var dev in list)
            {
                dev.Clear();
            }
        });
        BtnClearAllToMin.onClick.AddListener(() => {
            var list = DeviceManager.Instance.GetAllDevices();
            foreach (var dev in list)
            {
                dev.ClearToMin();
            }
        });
        BtnClearAllToMax.onClick.AddListener(() => {
            var list = DeviceManager.Instance.GetAllDevices();
            foreach (var dev in list)
            {
                dev.ClearToMax();
            }
        });

        InputUDPSendIP.text = UDP.SendIP;
        InputUDPSendPort.text = PlayerPrefs.GetInt("UDPSendPort", UDP.SendPort).ToString();
        InputUDPSendData.text = PlayerPrefs.GetString("UDPSendData", "");
        BtnUDPSend.onClick.AddListener(() => {
            UDP.SendIP = InputUDPSendIP.text;
            UDP.SendPort = int.Parse(InputUDPSendPort.text);
            UDP.Send(InputUDPSendData.text);
            PlayerPrefs.SetInt("UDPSendPort", UDP.SendPort);
            PlayerPrefs.SetString("UDPSendData", InputUDPSendData.text);
        });

        ToggleUDPDevRspFmt.onValueChanged.AddListener(v => UDP.DevRspFmt = v);

        ToggleLogUDPDevReq.onValueChanged.AddListener(v => UDP.DevReqLog = v);
        ToggleLogUDPDevRsp.onValueChanged.AddListener(v => UDP.DevRspLog = v);

        ToggleLogInfo.SetIsOnWithoutNotify(MyLogger.GetLevelFilter(0));
        ToggleLogWarning.SetIsOnWithoutNotify(MyLogger.GetLevelFilter(1));
        ToggleLogError.SetIsOnWithoutNotify(MyLogger.GetLevelFilter(2));

        ToggleLogInfo.onValueChanged.AddListener(v => MyLogger.SetLevelFilter(0, v));
        ToggleLogWarning.onValueChanged.AddListener(v => MyLogger.SetLevelFilter(1,v));
        ToggleLogError.onValueChanged.AddListener(v => MyLogger.SetLevelFilter(2, v));

        BtnClearLog.onClick.AddListener(() => MyLogger.Clear());
    }

    void UpdateLogLines()
    {
        ToggleLogInfo.GetComponentInChildren<Text>().text = $"Info ({MyLogger.GetLevelCount(0)})";
        ToggleLogWarning.GetComponentInChildren<Text>().text = $"Warning ({MyLogger.GetLevelCount(1)})";
        ToggleLogError.GetComponentInChildren<Text>().text = $"Error ({MyLogger.GetLevelCount(2)})";

        var count = MyLogger.GetCount();
        foreach (var item in _lineViewPool)
        {
            item.gameObject.SetActive(false);
        }

        var more = count - _lineViewPool.Count;
        for (var i = 0; i <= more; i++)
        {
            var newItem = Instantiate(LogLineViewTemplate.gameObject);
            newItem.SetActive(false);
            newItem.transform.SetParent(LogListRoot, false);
            var itemCtrl = newItem.GetComponent<LogLineView>();
            _lineViewPool.Add(itemCtrl);
            itemCtrl.onClick = (s) => { 
                LogLine.SetText(itemCtrl.DataForShow);
                LayoutRebuilder.MarkLayoutForRebuild(LogLine.transform.parent as RectTransform);
            };
        }

        MyLogger.ForeachLine((i, s) => {
            UnityEngine.Debug.Assert(i < _lineViewPool.Count, $"{i}<{_lineViewPool.Count}");
            var itemCtrl = _lineViewPool[i];
            itemCtrl.gameObject.SetActive(true);
            itemCtrl.UpdateLine(s.Level, s.Content);
        });

        LayoutRebuilder.MarkLayoutForRebuild(LogListRoot);
    }
}
